from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

from myapp.models import User
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib

import hmac
import base64
from hashlib import sha256
import urllib

import datetime

#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

#导入正则
import re

import cv2


from .myser import UserSer,CarouselSer

from myapp.models import User,Carousel


import redis

#定义ip和端口
host = 'localhost'
port = 6379

#建立连接
r = redis.Redis(host=host,port=port)





#插入幻灯片
class InsertPics(APIView):

	def get(self,request):

		#接收参数  dict['username']
		title = request.GET.get('title','null')
		link = request.GET.get('link','null')
		img = request.GET.get('img','null')


		#排重
		pics = Pics.objects.filter(name=title).first()

		if pics:
			res = {}
			res['code'] = 405
			res['message'] = '该活动已存在'
			return Response(res)

		#入库
		pic = Pics(name=title,sec=link,img=img)
		pic.save()

		res = {}
		res['code'] = 200
		res['message'] = '恭喜，添加成功'

		return Response(res)



# 删除幻灯片
class DePics(APIView):
    def post(self,request):
        id = request.data['id']
        Pics.objects.filter(id=id).delete()
        return Response({
            'code': 200
        })
    

# 修改幻灯片
class UpPics(APIView):
    def get(self,request):
        id = request.GET.get('id')
        title = request.GET.get('title')
        link = request.GET.get('link')
        img = request.GET.get('img')

        Pics.objects.filter(id=id).update(
            name=title,
            src=link,
            img=img
        )
        return Response({
            'code': 200
        })



#轮播图后台接口
class GetCarousel(APIView):

    def get(self,request):

        #读库
        carousel = Carousel.objects.all()

        #序列化操作
        carousel_ser = CarouselSer(carousel,many=True)

        return Response(carousel_ser.data)






import upyun



#又拍云创建文件夹
class Mkdir(APIView):

    def get(self,request):
        #接收参数
        mkdir = request.GET.get('mkdir',None)
        #新建又拍云实例
        up = upyun.UpYun('zl1907a', username='zl956973503', password='ZmEoFxTDnbqnQsfUArFufDjPl9afXrod')
        
        if mkdir:
            up.mkdir('/'+mkdir+'/')
            return Response({
                'code':200,
            })
        else:
            return Response({
                'code':500,
            })



#又拍云删除
class Del(APIView):

    def get(self,request):
        #接收参数
        filename = request.GET.get('filename',None)
        #新建又拍云实例
        up = upyun.UpYun('zl1907a', username='zl956973503', password='ZmEoFxTDnbqnQsfUArFufDjPl9afXrod')
        
        if filename:
            up.delete('/static/upload/'+filename)
            return Response({
                'code':200,
            })
        else:
            return Response({
                'code':500,
            })




#又拍云上传
class UploadFileUpyun(APIView):
    
    def post(self,request):

        img = request.FILES.get('file')

        up = upyun.UpYun('zl1907a', username='zl956973503', password='ZmEoFxTDnbqnQsfUArFufDjPl9afXrod')

        headers = { 'x-gmkerl-rotate': 'auto' }
        
        for chunk in img.chunks():
            res = up.put('../static/upload/'+ img.name, chunk, checksum=True, headers=headers)

        #返回结果
        # return HttpResponse(json.dumps({'filename':img.name}),content_type='application/json')

        return Response({
            'filename':json.dumps({'filename':img.name})
        })




from django.utils.deprecation import MiddlewareMixin

#自定义中间件类
class MyMiddleWare(MiddlewareMixin):

	#请求之前
	def process_request(self,request):
        
        # if request.path_info.startswith('/userinfo/'):
		uid = request.GET.get("uid",None)
		myjwt = request.GET.get('jwt',None)

		decode_jwt = jwt.decode(myjwt,'123',algorithms=['HS256'])
		if int(decode_jwt['uid']) != int(uid):
            # return JsonResponse({'mes':'你篡改了用户id'},safe=False,json_dumps_params={'ensure_ascii':False,'indent':4})
            
			return HttpResponse(json.dumps({'mes':'你篡改了用户id'},ensure_ascii=False,indent=4),content_type='application/json')

		# pass


	#模板渲染之前
	def process_view(self,request,view_func,view_args,view_kwargs):
		pass

	#请求之后
	def process_response(self,request,response):
		return response





from django.utils.decorators import method_decorator

#定义权限检测装饰器
def my_decorator(func):
    def wrapper(request,*args,**kwargs):

        #接收参数
        uid = request.GET.get('uid',None)
        myjwt = request.GET.get('jwt',None)

        try:
            #验证用户合法性
            decode_jwt = jwt.decode(myjwt,'123',algorithms=['HS256'])

        except Exception as e:
            return Response({
                'code':402,
                'mes':'您的密钥过期'
            })


        #进行对比
        #如果jwt没设置过期时间的判断
        # if int(uid) != int(decode_jwt['uid']):
        #如果jwt设置了过期时间的判断
        if int(uid) != int(decode_jwt['data']['uid']):
            return Response({
                'code':401,
                'mes':'您的密钥无权限'
            })


        return func(request,*args,**kwargs)
    
    return wrapper




#获取用户信息
class UserInfo(APIView):
    @method_decorator(my_decorator)
    def get(self,request):

        #接收参数
        uid = request.GET.get('uid',None)
        # myjwt = request.GET.get('jwt',None)

        # #验证用户合法性
        # decode_jwt = jwt.decode(myjwt,'123',algorithms=['HS256'])

        # #进行对比
        # if int(uid) != int(decode_jwt['uid']):
        #     return Response({
        #         'code':401,
        #         'mes':'您的密钥无权限'
        #     })

        user = User.objects.filter(id=int(uid)).first()
        user_ser = UserSer(user)
        return Response({
            'code':200,
            'user':user_ser.data
        })



#七牛云token
from qiniu import Auth

class Qiniu(APIView):

    def get(self,request):

        #声明认证对象
        q = Auth('uoXTznzcnkvm6NLVKGC5R4PTCf9bYZwJBLCkEvAl',
        'gezvzPNb1T9DjYFgt7BzIh9yGoZ50Zwy_GTGCEY9')

        #获取token
        token = q.upload_token('upload1907a')
        return Response({'token':token})



#文件上传通用类
class UploadFile(APIView):
    
    #post请求没有长度要求
    def post(self,request):
        #接收参数
        myfile = request.FILES.get('file')
        uid = request.POST.get('uid',None)

        #设置时间戳
        # time_stamp = str(int(time.time()))
        #设置图片名
        # img_name = time_stamp + myfile.name
        #建立文件流对象
        f = open(os.path.join(UPLOAD_ROOT,'',myfile.name),'wb')
        #写入
        for chunk in myfile.chunks():
            f.write(chunk)
        f.close()

        # 图像压缩
        img = cv2.imread(UPLOAD_ROOT+'/'+myfile.name)
        # jpg 压缩等级 0-100
        cv2.imwrite(UPLOAD_ROOT+'/'+myfile.name,img,[cv2.IMWRITE_JPEG_QUALITY,50])

        # 读图
        im = Image.open(UPLOAD_ROOT+'/'+myfile.name)
        #获取图片的长和宽
        im_width,im_height = im.size
        #设置水印字体和大小
        font = ImageFont.truetype(r'‪C:\Windows\Fonts\simkai.ttf',150)
        #生成画笔
        draw = ImageDraw.Draw(im)
        # #绘制  参数分别为坐标，文字，透明色
        draw.text((im_width-150*2,im_height-150),'周磊',fill=(76,234,124,180),font=font)
        # 存储图片
        im.save(UPLOAD_ROOT+'/'+myfile.name)

        #修改头像地址
        user = User.objects.get(id=int(uid))
        user.img = myfile.name
        user.save()

        return Response({
            'filename':myfile.name
        })





# 钉钉登录
def dingding_back(request):

    #获取code
    code = request.GET.get("code")

    t = time.time()
    #时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret ='ekohxJy88AhyaC8lLa1xnepQL5-CHRPXVs_8iZyLiVUnwhSdl4z4kMe5grz1Z_nI'
    #构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode('utf-8'),timestamp.encode('utf-8'), digestmod=sha256).digest())
    #请求接口，换取钉钉用户名
    payload = {'tmp_auth_code':code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode("utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoaoqugakgcsnfqqp5e",data=json.dumps(payload),headers=headers)

    res_dict = json.loads(res.text)
    print(res_dict['user_info']['nick'])

    dingding_nick = res_dict['user_info']['nick']

    #判断该用户是否曾经登陆过
    user = User.objects.filter(username=dingding_nick).first()


    user_id = ''

    if user:
        dingding_nick = user.username
        user_id = user.id

    else:
        #手动创建账号
        user = User(username = str(dingding_nick),password = '')
        user.save()
        


        #查询一下刚刚入库的新账号id
        user = User.objects.filter(username = str(dingding_nick)).first()
        user_id = user.id



    return redirect('http://127.0.0.1:8080/?sina_id='+str(dingding_nick)+'&uid='+str(user_id))
    # return HttpResponse(res.text)



#新浪微博回调方法
def weibo(request):

    #接收参数
    code = request.GET.get('code',None)

    #定义token的接口地址
    url = 'https://api.weibo.com/oauth2/access_token'

    #定义参数
    re = requests.post(url,data={
        'client_id':'1313226958',
        'client_secret':'cf9c28cf12db66ed57f2ba04c3bf2fdb',
        'grant_type':'authorization_code',
        'code':code,
        'redirect_uri':'http://127.0.0.1:8000/weibo/'
    })

    print(re.json())

    # 换取新浪微博用户昵称
    res = requests.get('https://api.weibo.com/2/users/show.json',params={'access_token':re.json()['access_token'],'uid':re.json()['uid']})

    print(res.json())

    sina_id = ''
    user_id = ''

    #判断是否用新浪微博登陆国
    user = User.objects.filter(username = str(res.json()['name'])).first()

    if user:
        #代表曾经用该账号登陆国
        sina_id = user.username
        user_id = user.id
    else:
        #首次登陆
        user = User(username=str(res.json()['name']))
        user.save()
        user = User.objects.filter(username = str(res.json()['name'])).first()
        
        sina_id = user.username
        user_id = user.id
    print(sina_id,user_id)

    return redirect('http://localhost:8080/?sina_id='+str(sina_id)+'&uid='+str(user_id))
    # return HttpResponse('回调成功')



#自定义图片验证码
class MyCode(View):

    #定义rbg随机颜色
    def get_random_color(self):
        
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)

        return (R,G,B)

    #定义图片视图
    def get(self,request):

        #画布
        img_size = (120,50)
        #定义图片对象
        image = Image.new('RGB',img_size,'white')
        #定义画笔
        draw = ImageDraw.Draw(image,'RGB')
        source = '123456879'
        #接受容器
        code_str = ''
        #定义字体
        # my_font = ImageFont.truetype(font='C:\\Windows\\Fonts\\simkai.ttf',size=15)
        for i in range(4):
            #获取字母颜色
            text_color = self.get_random_color()
            #获取随机下标
            tmp_num = random.randrange(len(source))
            #随机字符串
            random_str = source[tmp_num]
            #装入容器
            code_str += random_str
            #绘制字符串
            draw.text((10+30*i,20),random_str,text_color)
        #获取缓存区
        buf = io.BytesIO()
        #将临时图片保存到缓存
        image.save(buf,'png')
        #保存session
        request.session['code'] = code_str
        #保存随机码
        r.set('code',code_str)
        print(r.get('code'))
        
        return HttpResponse(buf.getvalue(),'image/png')





#md5加密方法
def make_password(mypass):

    #生成md5对象
    md5 = hashlib.md5()

    #转码
    mypass_utf8 = str(mypass).encode(encoding="utf-8")

    #加密操作
    md5.update(mypass_utf8)

    #返回密文
    return md5.hexdigest()




#登陆接口
class Login(APIView):

    def get(self,request):

        #接受参数
        username = request.GET.get('username',None)
        password = request.GET.get('password',None)
        code = request.GET.get('code',None)
        print(code)

        #将用户名以列表形式存入redis
        r.lpush(username,username)
        r.expire(username,60)

        #判断列表中的元素个数
        if r.llen(username) >5:
            return Response({
                'code':403,
                'mes':'输入超过五次，请在60秒后重新输入'
            })


        #查询数据
        user = User.objects.filter(Q(username=username) | Q(phone=username),password=make_password(password)).first()


        if user:
            
            palyload = {

                #过期时间
                'exp':int((datetime.datetime.now() + datetime.timedelta(seconds=10)).timestamp()),
                'data':{'uid':user.id}
            }

            #生成用户token
            #不设置过期时间为
            # encode_jwt = jwt.encode({'user':user.id},'123',algorithm='HS256')
            encode_jwt = jwt.encode(palyload,'123',algorithm='HS256')
            encode_str = str(encode_jwt,'utf-8')

            #从session取值
            # session_code = request.session.get('code',None)
            # print(session_code)

            #获取redis中的验证码
            r_code = r.get('code').decode('utf-8')
            print(r_code)
            #判断验证码
            if code != r_code:

                return Response({
                    'code':403,
                    'mes':'验证码错误',
                })


            return Response({
                'code':200,
                'mes':'登陆成功',
                'uid':user.id,
                'username':user.username,
                'jwt':encode_str
            })
        else:
            return Response({
                'code':403,
                'mes':'用户名或密码错误'
                
            })




#注册接口
class Register(APIView):

    def get(self,request):

        #接收参数
        username = request.GET.get('username',None)
        password = request.GET.get('password',None)
        phone = request.GET.get('phone',None)
        #排重操作
        user = User.objects.filter(username=username).first()

        if user:
            return Response({
                'code':403,
                'mes':'该用户名已经存在'
            })

        if not re.match(r"^1[35678]\d{9}$",phone):
            return Response({
                'code':403,
                'mes':'手机号码不符合要求'
            })

        # 入库
        user = User(username=username,password=make_password(password),phone=phone)
        # 保存结果
        user.save()

        return Response({
            'code':200,
            'mes':'恭喜注册成功'
        })
    



#更新用户信息
class UpdateUser(APIView):

    def get(self,request):
        
        # 获取参数
        id = request.GET.get('uid',None)
        password = request.GET.get('password',None)
        
        #查询用户
        user = User.objects.filter(id=id).first()

        #判断用户是否存在
        if user:
            user.password = make_password(password)
            user.save()
            
            return Response({
                'code':'200',
                'mes':'修改成功'
            })
        return Response({
            'code':403,
            'mes':'修改失败'
        })
